/**
 * 
 */
package np.com.baralsujan.login.da.impl;

import java.util.List;
import java.util.Map;

import np.com.baralsujan.login.da.IUserDao;
import np.com.baralsujan.login.da.SessionFactoryUtil;
import np.com.baralsujan.login.domain.User;
import np.com.baralsujan.login.util.AuthenticationException;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

/**
 * @author sujan
 *
 */
@Repository
public class UserDao implements IUserDao {
	
	private SessionFactory sessionFactory;
	
	public UserDao() {
		this.sessionFactory = SessionFactoryUtil.getInstance();
	}
	
	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#saveUser(np.com.baralsujan.login.domain.User)
	 */
	@Override
	public User saveUser(User user) {
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		session.save(user);
		tx.commit();
		return user;
	}
	
	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#retrieveUserByUsername(java.lang.String)
	 */
	@Override
	public User retrieveUserByUsername(String username) {
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		Query query = session.createQuery("from User where username = :username");
		query.setString("username", username);
		User user = (User) query.uniqueResult();
		tx.commit();
		return user;
	}

	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#getSessionFactory()
	 */
	@Override
	public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#setSessionFactory(org.hibernate.SessionFactory)
	 */
	@Override
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#updateUser(np.com.baralsujan.login.domain.User)
	 */
	@Override
	public void updateUser(User user) {
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		session.update(user);
		tx.commit();
	}

	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#deleteUser(np.com.baralsujan.login.domain.User)
	 */
	@Override
	public boolean deleteUser(User user) {
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		try {
			session.delete(user);
			tx.commit();
		} catch (HibernateException he) {
			return false;
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see np.com.baralsujan.login.da.IUserDao#authenticateUser(java.util.Map)
	 */
	@Override
	public User authenticateUser(Map<String, Object> criteria) throws AuthenticationException {
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		Criteria selectCriteria = session.createCriteria(User.class);
		for (String key : criteria.keySet()) {
			selectCriteria.add(Restrictions.eq(key, criteria.get(key)));
		}
		@SuppressWarnings("unchecked")
		List<User> users = selectCriteria.list();
		tx.commit();
		if(users != null & users.size() == 1) {
			return users.get(0);
		} else {
			throw new AuthenticationException("Username or password incorrect");
		}
	}

}
